﻿using SharpDepend.Architecture.Windows;
using System;
using System.Windows;
using System.Windows.Controls;

namespace SharpDepend.WPF.Architecture.Windows
{
    public class ZWindow : Window
    {
        public ZWindow()
        {

        }

        public event Action OnHiding;

        internal void RaiseOnHiding()
        {
            if (OnHiding != null)
            {
                OnHiding();
            }
        }
    }

    public class BaseWindow<TWindowContent, TController, TApplication>
        : UserControl, IWindowBase<TApplication>
        where TWindowContent : UserControl, IWindowContent<TController, TApplication>
        where TController : class, IController<TApplication>
    {
        private bool mIsShown;

        /// <summary>
        /// Get the parent window of this control.
        /// </summary>
        public ZWindow ParentWindow { get; private set; }

        public TWindowContent WindowContent { get; private set; }

        public IBaseWindowContent<TApplication> Window
        {
            get { return WindowContent; }
        }
        
        public event Action OnClosing;

        public BaseWindow(TApplication application)
        {
            WindowContent = Activator.CreateInstance<TWindowContent>();

            CheckIWindowInstance();

            string title = WindowContent.Title;

            double width = ((UserControl)WindowContent).Width;
            double height = ((UserControl)WindowContent).Height;
            ((UserControl)WindowContent).Width = double.NaN;
            ((UserControl)WindowContent).Height = double.NaN;

            //ParentWindow = WindowFactory.GetToolWindow(title, WindowContent, application.HostWindow);
            ParentWindow = new ZWindow();
            ParentWindow.Content = WindowContent;
            ParentWindow.Closing += ParentWindow_Closing;

            ParentWindow.Width = width;
            ParentWindow.Height = height;

            WindowContent.Initialize(application, this);
        }

        /// <summary>
        /// Calls when window is closing.
        /// </summary>
        void ParentWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (mIsShown)
            {
                if (OnClosing != null)
                {
                    OnClosing();
                }

                mIsShown = false;
            }
        }

        /// <summary>
        /// Show dialog if not already is showed.
        /// </summary>
        /// <param name="parameter">Optional extra parameter.</param>
        public void Show(object parameter)
        {
            if (!ParentWindow.IsVisible)
            {
                ParentWindow.Show();

                WindowContent.OnShown(parameter);

                // Update title again. It can be dynamically changed.
                string title = WindowContent.Title;
                ParentWindow.Title = title;

                mIsShown = true;
            }
            else
            {
                // Just show the parameter.
                WindowContent.OnShown(parameter);
                string title = WindowContent.Title;
                ParentWindow.Title = title;
            }
        }

        /// <summary>
        /// Check method.
        /// </summary>
        private void CheckIWindowInstance()
        {
            Type type = WindowContent.GetType();

            if (ContainsInterface<IBaseWindowContent<TApplication>>(type))
            {
                return;
            }

            throw new Exception("Windows is not a part of IBaseWindowContent<TApplication>.");
        }

        private static bool ContainsInterface<T>(Type type)
        {
            Type[] interfaces = type.GetInterfaces();

            foreach (var interf in interfaces)
            {
                if (interf == typeof(T))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Close window.
        /// </summary>
        public void Close()
        {
            ParentWindow.Close();
        }

        public bool IsOpen
        {
            get { return mIsShown; }
        }

        public string Title
        {
            get
            {
                return ParentWindow.Title;
            }
            set
            {
                ParentWindow.Title = value;
            }
        }
    }
}
